/**
  ******************************************************************************
  * @file    Libraries/Device/TS32F020X/TS32F020X_LL_Driver/src/ts32f020x_ll_uart.c
  * @author  JUSHENG Application Team
  * @version V1.0.0
  * @date    02-19-2022
  * @brief   This file contains all the UART LL firmware functions.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2022 JUSHENG</center></h2>
  *
  *
  *
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "include.h"

/** @addtogroup UART_LL_Driver UART LL Driver
  * @ingroup  uart_interface_gr
  * @{
  */
  
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/** @defgroup UART_LL_Inti_Cfg UART LL Initialization And Configuration
  * @ingroup  UART_LL_Driver
  * @brief    UART LL Initialization And Configuration
  * @{
  */

/**
  * @brief  Link layer UART 232 initialization function
  * @param  p_uart: The structure pointer of the UART group (UART0) is selected.
  * @param  p_cfg  : UART Configuration struct
  * @retval None.
  */
void ll_uart_init(UART_TypeDef *p_uart, TYPE_LL_UART_INIT *p_init)
{
    u32 uart_con = 0;

    ll_uart_baudrate_set(p_uart, p_init->baudrate);
    uart_con = p_uart->CON;
    if(p_init->work_mode)
    {
        uart_con |= LL_UARTX_CON_UART_WORK_MODE;
    }
    else
    {
        uart_con &= ~(LL_UARTX_CON_UART_WORK_MODE);
    }
    uart_con = (uart_con & (~LL_UARTX_CON_UART_TO_BIT_LEN_SET(ALL_WORD_FF))) | LL_UARTX_CON_UART_TO_BIT_LEN_SET(p_init->timeout_len);
    if(LL_UART_WORD_LENGTH_9B == p_init->bit_width_sel)
    {
        uart_con = uart_con | LL_UARTX_CON_UART_9BIT_EN;
        uart_con = uart_con & (~LL_UARTX_CON_UART_PARITY_EN);
    }
    else
    {
        uart_con = uart_con & (~LL_UARTX_CON_UART_9BIT_EN);
        if(LL_UART_PARITY_NO == p_init->parity)
        {
            uart_con = uart_con & (~LL_UARTX_CON_UART_PARITY_EN);
        }
        else if(LL_UART_PARITY_ODD == p_init->parity)
        {
            uart_con = uart_con | LL_UARTX_CON_UART_PARITY_EN;
            uart_con = uart_con | LL_UARTX_CON_UART_ODD_EN;
        }
        else
        {
            uart_con = uart_con | LL_UARTX_CON_UART_PARITY_EN;
            uart_con = uart_con & (~LL_UARTX_CON_UART_ODD_EN);
        }
    }
    if(LL_UART_STOP_2B == p_init->stop_bit_sel)
    {
        uart_con = uart_con | LL_UARTX_CON_UART_STOP_BIT;
    }
    else
    {
        uart_con = uart_con & (~LL_UARTX_CON_UART_STOP_BIT);
    }
    p_uart->CON = uart_con;
}

/**
  * @brief  Link layer UART interrupt initialization function
  * @param  p_uart: The structure pointer of the UART group (UART0) is selected.
  * @param  p_cfg  : UART Configuration struct
  * @retval None.
  */
void ll_uart_ie_config(UART_TypeDef *p_uart, TYPE_LL_UART_IE_CFG *p_cfg)
{
    u32 uart_ier = 0;
    uart_ier = p_uart->CON;
    if(p_cfg->uart_txbuf_empty_ie)
    {
        uart_ier |= LL_UARTX_CON_UART_TXBUF_EMPTY_IE;
    }
    else
    {
        uart_ier &= ~LL_UARTX_CON_UART_TXBUF_EMPTY_IE;
    }
    if(p_cfg->uart_rxbuf_not_empty_ie)
    {
        uart_ier |= LL_UARTX_CON_UART_RXBUF_NOT_EMPTY_IE;
    }
    else
    {
        uart_ier &= ~LL_UARTX_CON_UART_RXBUF_NOT_EMPTY_IE;
    }
     p_uart->CON = uart_ier;
}

/**
  * @}
  */

/** @defgroup UART_LL_Data_Transfers UART LL Data transfers functions
  * @ingroup  UART_LL_Driver
  * @brief    UART LL Data transfers functions 
  * @{
  */

/**
  * @brief  Link layer UART tx complete interrupt enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_tx_complete_interrupt_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_TC_IE;
}

/**
  * @brief  Link layer UART tx complete interrupt disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_tx_complete_interrupt_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= (~LL_UARTX_CON_UART_TC_IE);
}

/**
  * @brief  Link layer UART timeout interrupt enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_rx_timeout_interrupt_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_TO_IE;
}

/**
  * @brief  Link layer UART timeout interrupt disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_rx_timeout_interrupt_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= (~LL_UARTX_CON_UART_TO_IE);
}

/**
  * @brief  Link layer UART frame err interrupt enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_ferr_interrupt_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_FERR_IE;
}

/**
  * @brief  Link layer UART frame err interrupt disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_ferr_interrupt_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= (~LL_UARTX_CON_UART_FERR_IE);
}

/**
  * @brief  Link layer UART send buffer empty interrupt enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_tx_buf_empty_interrupt_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_TXBUF_EMPTY_IE;
}

/**
  * @brief  Link layer UART send buffer empty interrupt disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_tx_buf_empty_interrupt_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= (~LL_UARTX_CON_UART_TXBUF_EMPTY_IE);
}

/**
  * @brief  Link layer UART receive buffer not empty interrupt enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_rx_buf_not_empty_interrupt_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_RXBUF_NOT_EMPTY_IE;
}

/**
  * @brief  Link layer UART receive buffer not empty interrupt disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_rx_buf_not_empty_interrupt_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= (~LL_UARTX_CON_UART_RXBUF_NOT_EMPTY_IE);
}

/**
  * @brief  Link layer UART rx close enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_rx_close_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_RX_CLOSE_EN;
}

/**
  * @brief  Link layer UART rx close disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_rx_close_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= ~(LL_UARTX_CON_RX_CLOSE_EN);
}
/**
  * @brief  Link layer UART tmr pwm output enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_tmr_pwm_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_TMR_PWM_EN;
}

/**
  * @brief  Link layer UART tmr pwm output disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_tmr_pwm_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= ~(LL_UARTX_CON_UART_TMR_PWM_EN);
}

/**
  * @brief  Link layer UART rx timeout enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_rx_timeout_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_TO_EN;
}

/**
  * @brief  Link layer UART rx timeout disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_rx_timeout_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= ~(LL_UARTX_CON_UART_TO_EN);
}

/**
  * @brief  Link layer UART tx inv enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_tx_inv_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_TX_INV_EN;
}

/**
  * @brief  Link layer UART tx inv disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_tx_inv_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= ~(LL_UARTX_CON_UART_TX_INV_EN);
}

/**
  * @brief  Link layer UART rx inv enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_rx_inv_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_RX_INV_EN;
}

/**
  * @brief  Link layer UART rx inv disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_rx_inv_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= ~(LL_UARTX_CON_UART_RX_INV_EN);
}

/**
  * @brief  Link layer UART odd enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_odd_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_ODD_EN;
}

/**
  * @brief  Link layer UART odd disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_odd_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= ~(LL_UARTX_CON_UART_ODD_EN);
}

/**
  * @brief  Link layer UART parity enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_parity_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_PARITY_EN;
}

/**
  * @brief  Link layer UART parity disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_parity_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= ~(LL_UARTX_CON_UART_PARITY_EN);
}

/**
  * @brief  Link layer UART 9bit enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_9bit_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_9BIT_EN;
}

/**
  * @brief  Link layer UART 9bit disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_9bit_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= ~(LL_UARTX_CON_UART_9BIT_EN);
}

/**
  * @brief  Link layer UART enable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_enable(UART_TypeDef *p_uart)
{
    p_uart->CON |= LL_UARTX_CON_UART_EN;
}

/**
  * @brief  Link layer UART disable
  * @param  p_uart: The structure pointer of the UART is selected
  * @retval None
  */
void ll_uart_disable(UART_TypeDef *p_uart)
{
    p_uart->CON &= ~(LL_UARTX_CON_UART_EN);
}

/**
  * @brief  uart baudrate set
  * @param  p_uart: The structure pointer of the UART group (UART0) is selected.
  * @param  baudrate: uart baudrate.
  * @retval result.
  */
void ll_uart_baudrate_set(UART_TypeDef *p_uart, u32 baudrate)
{
    p_uart->BAUD = SYS_CLK / baudrate - 1;
}

/**
  * @brief  uart work mode get(duplex, single send, single receive, single auto)
  * @param  p_uart: The structure pointer of the UART group (UART0) is selected.
  * @retval work mode enum.
  */
TYPE_ENUM_LL_UART_WORK_MODE ll_uart_work_mode_get(UART_TypeDef *p_uart)
{
    return (TYPE_ENUM_LL_UART_WORK_MODE)(((p_uart->CON) >> 1) & 0x1);
}

/**
  * @brief  uart work mode set(duplex, single send, single receive, single auto)
  * @param  p_uart: The structure pointer of the UART group (UART0, UART1) is selected.
  * @param  work_mode: work mode enum.
  * @retval result.
  */
void ll_uart_work_mode_set(UART_TypeDef *p_uart, TYPE_ENUM_LL_UART_WORK_MODE work_mode)
{
    p_uart->CON = ((p_uart->CON & (~LL_UARTX_CON_UART_WORK_MODE)) | (work_mode << 1));
}

/**
  * @brief  uart irq tx
  * @param  p_uart: The structure pointer of the UART group (UART0) is selected.
  * @param  tx_data: tx uart data.
  * @retval result.
  * @note   uart tx done pending need clear in irq interrupt,and tx next data in the uart irq interrupt.
  */
void ll_uart_irq_tx(UART_TypeDef *p_uart, u16 tx_data)
{
    p_uart->DATA = tx_data;
}

/**
  * @brief  uart tx
  * @param  p_uart: The structure pointer of the UART group (UART0) is selected.
  * @param  tx_data: tx uart data.
  * @retval result.
  * @note   Uart tx done pending need clear in this function, because, not using irq.
  */
void ll_uart_tx(UART_TypeDef *p_uart,u16 tx_data)
{
    while(!LL_UART_TX_BUF_EMPTY_PENDING_GET(p_uart));
    p_uart->DATA = tx_data;
    //while(!LL_UART_TX_COMPLETE_PENDING_GET(p_uart));
    //LL_UART_TX_COMPLETE_PENDING_CLR(p_uart); //yh
}

/**
  * @brief  uart rx
  * @param  p_uart: The structure pointer of the UART group (UART0) is selected.
  * @param  rx_data: uart rx data.
  * @retval true or false.
  * @note   uart rx buf not empty  need clear or not in this function, because, chip can do when rx buf is empty.
  */
bool ll_uart_rx(UART_TypeDef *p_uart, u16 *rx_data)
{
    while(LL_UART_RX_BUF_NOT_EMPTY_PENDING_GET(p_uart))
    {
        *rx_data = p_uart->DATA;
        /* p_uart->UARTSTA = UARTX_STA_RX_BUF_NOT_EMPTY; */
    return true;
    }
    return false;
}

/**
  * @brief  uart tx inv en get
  * @param  p_uart: The structure pointer of the UART group (UART0) is selected.
  * @retval ENABLE or DISABLE.
  */
FunctionalState ll_uart_tx_inv_en_get(UART_TypeDef *p_uart)
{
    if((p_uart->CON) & LL_UARTX_CON_UART_TX_INV_EN)
    {
        return ENABLE;
    }
    else
    {
        return DISABLE;
    }
}

/**
  * @brief  uart rx inv en get
  * @param  p_uart: The structure pointer of the UART group (UART0) is selected.
  * @retval ENABLE or DISABLE.
  */
FunctionalState ll_uart_rx_inv_en_get(UART_TypeDef *p_uart)
{
    if((p_uart->CON) & LL_UARTX_CON_UART_RX_INV_EN)
    {
        return ENABLE;
    }
    else
    {
        return DISABLE;
    }
}

/**
  * @brief  uart 9bit en get
  * @param  p_uart: The structure pointer of the UART group (UART0) is selected.
  * @retval ENABLE or DISABLE.
  */
FunctionalState ll_uart_9bit_en_get(UART_TypeDef *p_uart)
{
    if((p_uart->CON) & LL_UARTX_CON_UART_9BIT_EN)
    {
        return ENABLE;
    }
    else
    {
        return DISABLE;
    }
}

/** 
  * @brief  uart config
  * @param  p_uart: The structure pointer of the UART group (UART1) is selected.
  * @param  baudrate: time interval.
  * @param  parity: parity
  * @retval result.
  * @note   unit : uart clock, bit[16]~bit[31], time interval from re falling edge to de rising edge
  */
void ll_uart_config(UART_TypeDef *p_uart, u32 baudrate, TYPE_ENUM_LL_UART_PARITY_SEL parity)
{
    p_uart->BAUD = SYS_CLK/baudrate - 1;
    if(parity == LL_UART_PARITY_ODD)
    {
        p_uart->CON |= LL_UARTX_CON_UART_PARITY_EN;
        p_uart->CON |= LL_UARTX_CON_UART_ODD_EN;
    }else if(parity == LL_UART_PARITY_EVEN)
    {
        p_uart->CON |= LL_UARTX_CON_UART_PARITY_EN;
        p_uart->CON &= (~LL_UARTX_CON_UART_ODD_EN);
    }else
    { 
       p_uart->CON &= (~LL_UARTX_CON_UART_PARITY_EN);
       p_uart->CON &= (~LL_UARTX_CON_UART_ODD_EN);
    }
}

/** 
  * @brief  uart config extend
  * @param  p_uart: The structure pointer of the UART group (UART1) is selected.
  * @param  baudrate: time interval.
  * @param  bit_width_sel: 8 or 9
  * @param  parity: None Odd Even
  * @param  stop_bit_sel: 1 or 2
  * @param  work_mode : work method
  * @retval result.
  * @note   unit : uart clock, bit[16]~bit[31], time interval from re falling edge to de rising edge
  */
void ll_uart_config_ex(UART_TypeDef *p_uart, u32 baudrate, TYPE_ENUM_LL_UART_BIT_WIDTH_SEL bit_width_sel, \
                       TYPE_ENUM_LL_UART_PARITY_SEL parity, TYPE_ENUM_LL_UART_STOP_BIT_SEL stop_bit_sel, TYPE_ENUM_LL_UART_WORK_MODE  work_mode)
{
    TX_ASSERT((UART0 == p_uart) || (UART1 == p_uart));
    u32 uart_con = 0;
    ll_uart_baudrate_set(p_uart, baudrate);
    uart_con = p_uart->CON;
    //uart_con = (uart_con & (~LL_UARTX_CON_UART_WORK_MODE_MASK)) | LL_UARTX_CON_UART_WORK_MODE(work_mode);
    uart_con = uart_con | (work_mode <<1);
    if(LL_UART_WORD_LENGTH_9B == bit_width_sel)
    {
        uart_con = uart_con | LL_UARTX_CON_UART_9BIT_EN;
        uart_con = uart_con & (~LL_UARTX_CON_UART_PARITY_EN);
    }
    else
    {
        uart_con = uart_con & (~LL_UARTX_CON_UART_9BIT_EN);
        if(LL_UART_PARITY_NO == parity)
        {
            uart_con = uart_con & (~LL_UARTX_CON_UART_PARITY_EN);
        }
        else if(LL_UART_PARITY_ODD == parity)
        {
            uart_con = uart_con | LL_UARTX_CON_UART_PARITY_EN;
            uart_con = uart_con | LL_UARTX_CON_UART_ODD_EN;
        }
        else
        {
            uart_con = uart_con | LL_UARTX_CON_UART_PARITY_EN;
            uart_con = uart_con & (~LL_UARTX_CON_UART_ODD_EN);
        }
    }
    if(LL_UART_STOP_2B == stop_bit_sel)
    {
        uart_con = uart_con | LL_UARTX_CON_UART_STOP_BIT;
    }
    else
    {
        uart_con = uart_con & (~LL_UARTX_CON_UART_STOP_BIT);
    }
    p_uart->CON = uart_con;
}



/** 
  * @brief  uart work mode config
  * @param  p_uart: The structure pointer of the UART group (UART1) is selected.
  * @param  work_mode : work method
  */
void ll_uart_mode_sel(UART_TypeDef *p_uart, TYPE_ENUM_LL_UART_WORK_MODE work_mode)
{
    if(work_mode)
    {
        p_uart->CON |= LL_UARTX_CON_UART_WORK_MODE;
    }
    else
    {
        p_uart->CON &= ~(LL_UARTX_CON_UART_WORK_MODE);
    }

}

/** 
  * @brief  uart set timeout bit len
  * @param  p_uart: The structure pointer of the UART group (UART1) is selected.
  * @param  timeout_bit : timeout bit
  * @note   timeout time = (timeout_bit + 1)*Bit_Rate     defalut timeout time = (55+1)*Bit_Rate
  */
void ll_uart_set_timeout_bit_len(UART_TypeDef *p_uart, u8 timeout_bit)
{
    p_uart->CON = (p_uart->CON & (~LL_UARTX_CON_UART_TO_BIT_LEN_SET(ALL_WORD_FF))) | LL_UARTX_CON_UART_TO_BIT_LEN_SET(timeout_bit);
}

/**
  * @}
  */

/**
  * @}
  */

/*************************** (C) COPYRIGHT 2022 JUSHENG ***** END OF FILE *****/
